package com.wind.utils.file;

import com.wind.utils.GlobalConst;

import java.io.*;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;

/**
 * <p>
 *      csv
 * </p>
 * @author wind
 * @date    2024/12/11 15:13
 * @version v1.0
 */
public class CsvUtil {

    private static final String COMMA = ",";


    private CsvUtil(){

    }

    /**
     * 读取CSV文件到List<List<String>>, 默认不做处理
     * @param filePath 文件路径
     * @return 包含每行数据的Map列表
     * @throws IOException 如果发生I/O错误
     */
    public static List<List<String>> read(String filePath) throws IOException {
        return read(filePath, false, GlobalConst.CHARSET.UTF8);
    }

    /**
     * 读取CSV文件到List<List<String>>, 默认不做处理
     * @param filePath 文件路径
     * @return 包含每行数据的Map列表
     * @throws IOException 如果发生I/O错误
     */
    public static List<List<String>> read(String filePath, String charset) throws IOException {
        return read(filePath, false, charset);
    }

    /**
     * 读取CSV文件到List<List<String>>
     * @param filePath 文件路径
     * @param endEmpty 是否已空格结束，若为true，列数取值第一行第一列到第一行出现第一个空值结束
     *        行数取值第一行到出现第一个空行结束，false则不做处理
     * @param charset 字符编码
     * @return 包含每行数据的Map列表
     * @throws IOException 如果发生I/O错误
     */
    public static List<List<String>> read(String filePath, boolean endEmpty, String charset) throws IOException {
        List<List<String>> dataList = new ArrayList<>();
        try (BufferedReader br = new BufferedReader(new InputStreamReader(Files.newInputStream(Paths.get(filePath)), getCharset(charset)))) {
            String line = br.readLine();
            List<String> headerList = getFirst(line, endEmpty);
            dataList.add(headerList);
            while ((line = br.readLine()) != null) {
                String[] values = line.split(COMMA);
                List<String> rowList = new ArrayList<>();
                int emptyCount = 0;
                for (int i = 0; i < headerList.size(); i++) {
                    if(i < values.length){
                        rowList.add(values[i]);
                    }else{
                        rowList.add("");
                        emptyCount++;
                    }
                }
                if(endEmpty && emptyCount == headerList.size()){
                    break;
                }
                dataList.add(rowList);
            }
        }
        return dataList;
    }

    /**
     * 将List<Map<String, String>>写入CSV文件
     *
     * @param dataList 数据列表
     * @param filePath 文件路径
     * @throws IOException 如果发生I/O错误
     */
    public static void write(String filePath, List<List<String>> dataList) throws IOException {
        write(filePath, dataList, GlobalConst.CHARSET.UTF8);
    }

    /**
     * 将List<Map<String, String>>写入CSV文件
     *
     * @param filePath 数据列表
     * @param dataList 文件路径
     * @throws IOException 如果发生I/O错误
     */
    public static void write(String filePath, List<List<String>> dataList, String charset) throws IOException {
        try (BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(filePath)), getCharset(charset)))) {
            int count = 0;
            for (List<String> row : dataList) {
                count++;
                String rowLine = String.join(COMMA, row);
                bw.write(rowLine);
                if(count < dataList.size()){
                    bw.write("\n");
                }
            }
        }
    }

    /**
     * 读取CSV文件到List<List<String>>, 默认不做处理
     * @param filePath 文件路径
     * @return 包含每行数据的Map列表
     * @throws IOException 如果发生I/O错误
     */
    public static List<Map<String, String>> readMap(String filePath) throws IOException {
        return readMap(filePath, false, GlobalConst.CHARSET.UTF8);
    }

    /**
     * 读取CSV文件到List<Map<String, String>>
     *
     * @param filePath 文件路径
     * @return 包含每行数据的Map列表
     * @throws IOException 如果发生I/O错误
     */
    public static List<Map<String, String>> readMap(String filePath, boolean endEmpty, String charset) throws IOException {
        List<Map<String, String>> dataList = new ArrayList<>();
        try (BufferedReader br = new BufferedReader(new InputStreamReader(Files.newInputStream(Paths.get(filePath)), getCharset(charset)))) {
            String line = br.readLine();
            List<String> headerList = getFirst(line, endEmpty);
            while ((line = br.readLine()) != null) {
                String[] values = line.split(COMMA);
                Map<String, String> dataMap = new LinkedHashMap<>();
                int emptyCount = 0;
                for (int i = 0; i < headerList.size(); i++) {
                    String value = "";
                    if(i < values.length){
                        value = values[i];
                    }else{
                        emptyCount++;
                    }
                    dataMap.put(headerList.get(i), value);
                }
                if(endEmpty && emptyCount == headerList.size()){
                    break;
                }
                dataList.add(dataMap);
            }
        }
        return dataList;
    }

    /**
     * 将List<Map<String, String>>写入CSV文件
     *
     * @param filePath 数据列表
     * @param dataList 文件路径
     * @throws IOException 如果发生I/O错误
     */
    public static void writeMap(String filePath, List<Map<String, String>> dataList) throws IOException {
        writeMap(filePath, dataList, GlobalConst.CHARSET.UTF8);
    }

    /**
     * 将List<Map<String, String>>写入CSV文件
     *
     * @param filePath 数据列表
     * @param dataList 文件路径
     * @throws IOException 如果发生I/O错误
     */
    public static void writeMap(String filePath, List<Map<String, String>> dataList, String charset) throws IOException {
        try (BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(filePath)), getCharset(charset)))) {
            if(dataList.isEmpty()){
                return;
            }
            int count = 0;
            for (Map<String, String> dataMap : dataList) {
                count++;
                if(count == 1){
                    String header = String.join(COMMA, dataMap.keySet());
                    bw.write(header);
                    bw.write("\n");
                }

                String row = String.join(COMMA, dataMap.values());
                bw.write(row);
                if(count < dataList.size()){
                    bw.write("\n");
                }
            }
        }
    }


    /**
     * 获取第一行数据
     * @param line
     * @param endEmpty
     * @return
     */
    private static List<String> getFirst(String line, boolean endEmpty){
        String[] headers = line.split(COMMA);
        List<String> headerList = new ArrayList<>();
        if(endEmpty){
            for (String header : headers) {
                if (header == null || "".equals(header)) {
                    break;
                }
                headerList.add(header);
            }
        }else{
            headerList.addAll(Arrays.asList(headers));
        }
        return headerList;
    }


    /**
     * 获取字符
     * @param charset
     * @return
     */
    private static String getCharset(String charset){
        if(charset == null || "".equals(charset.trim())){
            charset = Charset.defaultCharset().name();
        }
        return charset;
    }
}
